package stream02;

import org.junit.Before;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 中间操作:
 *   过滤操作
 *     filter:传入Predicate,根据Predicate中的条件对流中元素做筛选,满足条件保留,不满足剔除
 *   排序操作:
 *     sorted:可以根据指定的规则,将流中的元素从小到大排序
 *   去重操作
 *     distinct:去除流中重复的元素
 *   截取操作
 *     limit:根据传入的值,来决定截取流总元素的个数
 *     skip:根据传入的值,决定跳过流中的元素个数
 *   映射操作
 *     map:将一种数据根据指定操作映射成另外一种数据
 *       mapToInt
 *       mapToDouble
 *       mapToLong
 * 班级中有5个人姓名,语文成绩,数学成绩分别如下
 * 李雷, 70, 90
 * 韩梅梅,  30, 100
 * 李宁,  85, 80
 * 王松,70,60
 * 张家界,90,73
 *
 * 需求:
 *     1.打印语文成绩>80的学生信息
 *     2.打印数学成绩前三名的学生信息
 *     3.打印数学成绩倒数第一和倒数第二的学生信息
 *     4.获取全班数学的平均成绩
 *     5.获取全班语文成绩(不包含重复成绩)
 *     6.将语文成绩或数学成绩在[80,90]之间的学生的姓名收集到一个集合中
 */
public class StreamDemo04 {

	List<Student> students;

	@Before  //@Before会在所有的@Test注解之前之前
	public void init() {
		 //初始化数据源
		 students = Arrays.asList(
				new Student("李雷", 70, 90),
				new Student("韩梅梅", 30, 100),
				new Student("李宁", 85, 80),
				new Student("王松", 70, 60),
				new Student("张家界", 90, 73)

		);
	}

	@Test
	public void test02() {
		 //1.打印语文成绩>80的学生信息
		 students.stream().filter(stu->stu.getChineseScore()>80).forEach(System.out::println);
	}

	@Test
	public void test03() {
		//2.打印数学成绩前三名的学生信息
		/**
		 * a.首先需要对学生的数学成绩从大到小排序
		 * b.获取前三个的学生信息
		 */
		students.stream()
				.sorted((stu1,stu2)->(int)(stu2.getMathScore()-stu1.getMathScore()))
				.limit(3) //截取流中的前三个元素
		        .forEach(System.out::println);
	}

	@Test
	public void test04() {
		//3.打印数学成绩倒数第一和倒数第二的学生信息
		/**
		 * a.首先需要对学生的数学成绩从大到小排序
		 * b.获取倒数第一和倒数第二名
		 *  100 90 80  73 60
		 */
		students.stream()
				.sorted((stu1, stu2) -> (int) (stu2.getMathScore() - stu1.getMathScore()))
				.skip(students.size() - 2)
				.forEach(System.out::println);

	}

	@Test
	public void test05() {
		//4.获取全班数学的平均成绩
		//将流中的一个个学生对象映射成每个学生对应的数学成绩
		double avgScore = students.stream().mapToDouble(stu -> stu.getMathScore()).average().getAsDouble();
		System.out.println(avgScore);

	}

	@Test
	public void test06() {
		//5.获取全班语文成绩(不包含重复成绩)
		//需要使用mapToDouble
		//students.stream().mapToDouble(stu -> stu.getChineseScore()).distinct().forEach(System.out::println);
		//students.stream().map(stu->stu.getChineseScore()).distinct().forEach(System.out::println);
		students.stream().map(Student::getChineseScore).distinct().forEach(System.out::println);
	}

	@Test
	public void test07() {
		//6.将语文成绩或数学成绩在[80,90]之间的学生的姓名收集到一个集合中
		// a.语文成绩在[80,90]之间的学生 (Predicate) 或 数学成绩在[80,90]之间的学生(Predicate)
		// b.将过滤后的一个个学生对象映射成对应的学生姓名
		// c.将过滤和映射中间操作后的数据收集到一个集合中
		Predicate<Student> p1 = stu -> stu.getChineseScore()>=80 && stu.getChineseScore()<=90;
		Predicate<Student> p2 = stu -> stu.getMathScore()>=80 && stu.getMathScore()<=90;
		List<String> names = students.stream()
				.filter(p1.or(p2))
				.map(Student::getName)
				.collect(Collectors.toList());

		System.out.println(names);

	}
}
